package com.shyroke.daydayzhuansvc.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.querydsl.core.QueryResults;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.dto.AppDto;
import com.shyroke.daydayzhuanapi.dto.AppSearchRequest;
import com.shyroke.daydayzhuanapi.dto.LabelDto;
import com.shyroke.daydayzhuanapi.entity.AppEntity;
import com.shyroke.daydayzhuanapi.entity.AppLabelEntity;
import com.shyroke.daydayzhuanapi.entity.LabelEntity;
import com.shyroke.daydayzhuanapi.entity.QAppEntity;
import com.shyroke.daydayzhuanapi.mapper.AppMapper;
import com.shyroke.daydayzhuanapi.mapper.LabelMapper;
import com.shyroke.daydayzhuandao.respository.AppLabelRepository;
import com.shyroke.daydayzhuandao.respository.AppRepository;
import com.shyroke.daydayzhuandao.respository.LabelRepository;
import com.shyroke.daydayzhuansvc.service.IAppService;
import com.shyroke.daydayzhuansvc.util.Page;
import com.shyroke.daydayzhuansvc.util.TabelData;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class AppService implements IAppService {

    @Autowired
    private LabelRepository labelRepository;
    @Autowired
    private AppRepository appRepository;
    @Autowired
    private AppLabelRepository appLabelRepository;
    @Autowired
    private JPAQueryFactory factory;
    @Autowired
    private OSSService ossService;
    @Autowired
    private AppMapper appMapper;
    @Autowired
    private LabelMapper labelMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public TabelData<AppDto> getProjectInvateList(Page page, AppSearchRequest request) {
        QAppEntity qAppEntity = QAppEntity.appEntity;
        JPAQuery<AppEntity> query = factory.selectFrom(qAppEntity);
        if(request.getType() != null){
            query = query.where(qAppEntity.type.eq(request.getType()));
        }
        if(StrUtil.isNotBlank(request.getTitle())){
            query = query.where(qAppEntity.title.eq(request.getTitle()));
        }

        QueryResults<AppEntity> queryResults = query
                .offset(PageRequest.of(page.getPage() - 1, page.getLimit()).getOffset()).limit(page.getLimit())
                .orderBy(qAppEntity.offline.asc())
                .fetchResults();

        List<AppDto> list = queryResults.getResults().stream().map(e -> appMapper.entityToDto(e)).collect(Collectors.toList());
        return new TabelData(list,(int)queryResults.getTotal());
    }

    @Override
    public List<AppDto> findAll() {
        QAppEntity qAppEntity = QAppEntity.appEntity;
        List<AppEntity> list = factory.selectFrom(qAppEntity).orderBy(qAppEntity.createTime.desc()).fetch();
        return list.stream().map(e->appMapper.entityToDto(e)).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void save(AppDto app) {
        AppEntity appEntity2 = appMapper.dtoToEntity(app);
        appRepository.save(appEntity2);

        //关键词保存到label中
        List<AppLabelEntity> appLabelList = new ArrayList<>();
        String keyword = app.getKeyword();
        if(!StringUtils.isEmpty(keyword)){
            String[] split = keyword.split(",");
            for (String key : split) {
                LabelEntity existLabel = labelRepository.findByLabelName(key);
                if(existLabel == null){
                    existLabel = new LabelEntity();
                    existLabel.setIsShowTitle(0);
                    existLabel.setLabelName(key);
                    labelRepository.save(existLabel);

                    AppLabelEntity appLabel = new AppLabelEntity();
                    LabelEntity labelEntity = new LabelEntity();
                    labelEntity.setId(Integer.valueOf(existLabel.getId()));
                    appLabel.setLabelEntity(labelEntity);
                    AppEntity appEntity = new AppEntity();
                    appEntity.setId(appEntity2.getId());
                    appLabel.setAppEntity(appEntity);
                    appLabelList.add(appLabel);
                }else{
                    AppLabelEntity appLabel = new AppLabelEntity();
                    LabelEntity labelEntity = new LabelEntity();
                    labelEntity.setId(Integer.valueOf(existLabel.getId()));
                    appLabel.setLabelEntity(labelEntity);
                    AppEntity appEntity = new AppEntity();
                    appEntity.setId(appEntity2.getId());
                    appLabel.setAppEntity(appEntity);
                    appLabelList.add(appLabel);
                }
            }
        }

        if(CollectionUtils.isNotEmpty(appLabelList)){
            //批量插入项目_标签表
            appLabelRepository.saveAll(appLabelList);
        }

        redisTemplate.delete(RedisKeyPrefix.TOP_APP);
    }

    @Override
    public AppDto findById(Integer appId) {
        Optional<AppEntity> optionalAppEntity = appRepository.findById(appId);
        if (!optionalAppEntity.isPresent()) {
            return null;
        }
        return appMapper.entityToDto(optionalAppEntity.get());
    }

    @Override
    public void update(AppDto app) {
        Optional<AppEntity> optionalAppEntity = appRepository.findById(app.getId());
        AppEntity appEntity = appMapper.dtoToUpdateEntity(app,optionalAppEntity.get());
        appRepository.save(appEntity);

        //2、删除project_type project_label 关联
        List<AppLabelEntity> appLabels = appLabelRepository.findByAppId(app.getId());
        for (AppLabelEntity e : appLabels) {
            appLabelRepository.delete(e);
        }

        List<AppLabelEntity> appLabelList = new ArrayList<>();

        //关键词保存到label中
        String keyword = app.getKeyword();
        if(!StringUtils.isEmpty(keyword)){
            String[] split = keyword.split(",");
            for (String key : split) {
                LabelEntity existLabel = labelRepository.findByLabelName(key);
                if(existLabel == null){
                    existLabel = new LabelEntity();
                    existLabel.setIsShowTitle(0);
                    existLabel.setLabelName(key);
                    labelRepository.save(existLabel);

                    AppLabelEntity appLabel = new AppLabelEntity();
                    LabelEntity labelEntity = new LabelEntity();
                    labelEntity.setId(Integer.valueOf(existLabel.getId()));
                    appLabel.setLabelEntity(labelEntity);
                    AppEntity appEntity2 = new AppEntity();
                    appEntity2.setId(app.getId());
                    appLabel.setAppEntity(appEntity2);
                    appLabelList.add(appLabel);
                }else{
                    AppLabelEntity appLabel = new AppLabelEntity();
                    LabelEntity labelEntity = new LabelEntity();
                    labelEntity.setId(Integer.valueOf(existLabel.getId()));
                    appLabel.setLabelEntity(labelEntity);
                    AppEntity appEntity2 = new AppEntity();
                    appEntity2.setId(app.getId());
                    appLabel.setAppEntity(appEntity2);
                    appLabelList.add(appLabel);
                }
            }
        }

        if(CollectionUtils.isNotEmpty(appLabelList)){
            //批量插入项目_标签表
            appLabelRepository.saveAll(appLabelList);
        }

        redisTemplate.delete(RedisKeyPrefix.TOP_APP);
    }

    @Override
    public List<AppDto> findByTop(int count,boolean isShowLabel) {
        QAppEntity qAppEntity = QAppEntity.appEntity;
        List<AppEntity> list = factory.selectFrom(qAppEntity).where(qAppEntity.type.eq(1),qAppEntity.offline.eq(0))
                .orderBy(qAppEntity.downCount.desc()).limit(count).fetch();

        if(isShowLabel){
            setAppLabelList(list);
        }
        List<AppDto> dtoList = list.stream().map(e -> appMapper.entityToDto(e)).collect(Collectors.toList());
        dtoList.stream().forEach(app->{
            if(!StringUtils.isEmpty(app.getCover())){
                app.setCover(ossService.getImgUrl(app.getCover()));
            }
        });
        return dtoList;
    }

    private void setAppLabelList(List<AppEntity> list) {
        //设置对应标签
        List<Integer> appIdList = list.stream().map(a -> a.getId()).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(appIdList)){
            List<AppLabelEntity> appLabelList = appLabelRepository.findByAppIdIn(appIdList);
            Map<Integer, List<AppLabelEntity>> maps = appLabelList.stream().collect(Collectors.groupingBy(AppLabelEntity::getAppId));
            list.stream().forEach(app->{
                List<AppLabelEntity> appLabels = maps.get(app.getId());
                if(CollectionUtil.isNotEmpty(appLabels)){
                    List<LabelDto> lebelList = appLabels.stream().map(l -> labelMapper.entityToDto(l.getLabelEntity())).collect(Collectors.toList());
                    app.setLabelList(lebelList);
                }
            });
        }
    }

    @Override
    public List<AppDto> findByCreateTime(int i,boolean isShowLabel) {
        QAppEntity qAppEntity = QAppEntity.appEntity;
        List<AppEntity> list = factory.selectFrom(qAppEntity).where(qAppEntity.offline.eq(0))
                .orderBy(qAppEntity.updateTime.desc()).limit(i).fetch();
        if(isShowLabel){
            setAppLabelList(list);
        }
        List<AppDto> dtoList = list.stream().map(e -> appMapper.entityToDto(e)).collect(Collectors.toList());
        dtoList.stream().forEach(app->{
            if(!StringUtils.isEmpty(app.getCover())){
                app.setCover(ossService.getImgUrl(app.getCover()));
            }
        });
        return dtoList;
    }

    public List<AppDto> appList() {
        List<AppEntity> list = appRepository.findByOfflineOrderByIdDesc(0);
        return list.stream().map(e->appMapper.entityToDto(e)).collect(Collectors.toList());
    }

    public AppDto findAppInfo(Integer appId) {
        Optional<AppEntity> optionalApp = appRepository.findById(appId);
        if (!optionalApp.isPresent()) {
            return null;
        }
        AppEntity appEntity = optionalApp.get();
        AppDto appDto = appMapper.entityToDto(appEntity);
        if(StrUtil.isNotBlank(appDto.getCover())){
            appDto.setCover(ossService.getImgUrl(appDto.getCover()));
        }
        return appDto;
    }

    public void updateCount(Integer appId) {
        appRepository.updateCount(appId);
    }
}
